package com.yonyougov.devops.cruxcisupport.harbor.artifact;

import com.yonyougov.devops.cruxcisupport.app.AppEntity;
import com.yonyougov.devops.cruxcisupport.app.AppService;
import com.yonyougov.devops.cruxcisupport.enums.StatusEnum;
import com.yonyougov.devops.cruxcisupport.harbor.artifact.Dto.ReferencyAndVersion;
import com.yonyougov.devops.cruxcisupport.harbor.utils.HarborInfo;
import com.yonyougov.devops.cruxcisupport.harborhis.HarborHisEntity;
import com.yonyougov.devops.cruxcisupport.harborhis.HarborHisService;
import com.yonyougov.devops.cruxcisupport.harborhis.enums.HarborHisOperatorTypeEnum;
import com.yonyougov.devops.cruxcisupport.user.UserService;
import com.yonyougov.devops.cruxcisupport.version.VersionEntity;
import com.yonyougov.devops.cruxcisupport.version.VersionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.math.BigInteger;
import java.util.Date;
import java.util.List;
import java.util.Optional;

@Component
@Slf4j
public class HarborArtifactDao {
    @Autowired
    private HarborInfo harborInfo;
    @Autowired
    private AppService appService;
    @Autowired
    private VersionService versionService;
    @Autowired
    private HarborHisService harborHisService;
    @Autowired
    private UserService userService;

    public List<HarborArtifacts> getArtifacts(String projectName, String repositoryName, String tag, Integer page, Integer pageSize) {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setBasicAuth(harborInfo.getUsername(),harborInfo.getPassword());
        HttpEntity httpEntity = new HttpEntity(httpHeaders);
        //https://dockerhub.yonyougov.top/api/v2.0/projects/crux/repositories/base-image-arm64/artifacts
        String url = harborInfo.getUrl() + "projects/" + projectName + "/repositories/" + repositoryName + "/artifacts" + "?page=" + page + "&page_size=" + pageSize;
        if(StringUtils.isNotBlank(tag)){
            url = url + "&q=tags=~"+tag;
        }
        log.debug("获取项目: {}下仓库下: {}的镜像路径: {}",projectName,repositoryName,url);
        ResponseEntity<List<HarborArtifacts>> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, new ParameterizedTypeReference<List<HarborArtifacts>>() {
        });
        if(responseEntity.getStatusCode().value() == 200 && responseEntity.hasBody()){
            return responseEntity.getBody();
        }
        return null;
    }

    public void deleteArtifact(String projectName, String repositoryName, ReferencyAndVersion referencyAndVersion) {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setBasicAuth(harborInfo.getUsername(),harborInfo.getPassword());
        HttpEntity httpEntity = new HttpEntity(httpHeaders);
        //https://dockerhub.yonyougov.top/api/v2.0/projects/crux/repositories/crux-appmodule/artifacts/sha256%3A6783c69e2bc718715e6557b6cd6338686ed55b6d5e980e2c4121921cc99b1cfc
        String url = harborInfo.getUrl() + "projects/" + projectName + "/repositories/" + repositoryName + "/artifacts/" + referencyAndVersion.getReference();
        log.debug("删除项目: {}下仓库下: {}的镜像路径: {}",projectName,repositoryName,url);
        restTemplate.exchange(url, HttpMethod.DELETE, httpEntity,String.class);
        // 记录操作日志
        harborHisService.add(HarborHisEntity.builder()
                .projectName(projectName)
                .repositoryName(repositoryName)
                .imageVersion(Optional.ofNullable(referencyAndVersion.getVersion()).orElseGet(()->referencyAndVersion.getReference()))
                .operator(Optional.ofNullable(userService.getCurrentUser().getNickName()).orElseGet(()->userService.getCurrentUser().getUserName()))
                .operatorType(HarborHisOperatorTypeEnum.DELETE.getCode())
                .operatorTime(new Date())
                .build());
        //删除完之后,版本置为无效
        updateAppVersion(repositoryName,referencyAndVersion.getVersion());
    }
    /**
     * 镜像删除成功后将版本置为无效
     */
    private void updateAppVersion(String project, String version) {
        if(StringUtils.isNotBlank(version)){
            AppEntity appEntity = new AppEntity();
            appEntity.setApp(project);
            AppEntity app = appService.findBy(appEntity);
            if(null != app){
                BigInteger appId = app.getId();
                VersionEntity versionParam = new VersionEntity();
                versionParam.setAppId(appId);
                versionParam.setVersionName(version);
                VersionEntity versionEntity = versionService.findBy(versionParam);
                if(null != versionEntity){
                    versionEntity.setStatus(StatusEnum.Pass.getCode());
                    versionService.update(versionEntity);
                }
            }
        }
    }
    public boolean getArtifactByAppAndVersion(String projectName, String app, String version){
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setBasicAuth(harborInfo.getUsername(),harborInfo.getPassword());
        HttpEntity httpEntity = new HttpEntity(httpHeaders);
        String url = harborInfo.getUrl() + "projects/"+projectName + "/repositories/" + app + "/artifacts/" + version;
        log.debug("获取项目: {}下仓库下: {}的镜像,版本:{},路径：{}",projectName,app,version,url);
        ResponseEntity<HarborArtifacts> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, new ParameterizedTypeReference<HarborArtifacts>() {
        });
        if(responseEntity.getStatusCode().value() == 200 && responseEntity.hasBody()){
            return true;
        }
        return false;
    }
}
